// [] . 成员访问符

// JS 设计是就是以函数式编程为主，面向对象编程为辅的一个语言系统
//  对象定义方式
//  方式 1 : 基于构造方法创建对象
//          + JS 的对象构造方法的定义和普通方法的定义使用的是同一套语法
//          + 当方法通过 new 关键字进行调用时，该方法就被作为构造函数使用，具有面向对象的语法特性
//          + 在前端的语言体系中，存在一些约定的习惯，如果方法作为构造函数使用，名称采用大驼峰命名
function User() {
    console.log("User对象构造器函数")
}
let u1 = new User();
console.log( u1 )
let u2 = new User();
console.log( u2 )
console.log( u1==u2 )
let u3 = u2;
console.log( u3==u2 )

console.log("=======================")
// 对象构建时的成员属性，成员方法，静态属性，静态方法的定义
// a. 静态属性、静态方法的定义
//      定义语法：构造方法名.静态属性名|静态方法名 = 值
//      使用语法：构造方法名.静态属性名|静态方法名()
function Stu(){

}
Stu.info = "静态属性info";
Stu.tip = function (){
    console.log("静态方法tip")
}
console.log( Stu.info )
Stu.tip();
// JS 的对象静态属性和方法不能被实例调用的
// let s = new Stu();
// console.log( s.info )
// s.tip();

console.log("=======================")
// b. 成员属性定义
//      + 在JS的对象构造方法中，存在固定内置指代变量 this
//      + this 关键字指向与当前构造方法构建的实例对象
//      + 成员属性通过 对象.成员属性名 进行使用
function Student(username,age){
    console.log("Student构造方法:",username,age,this);
//    js 中对与对象的成员属性定义，直接通过 this.成员名= 成员值方式实现
    this.username = username;
    this.age = age;
    // this.test 定义的是成员属性
    this.test = function (){
        console.log("Studeng构造函数中通过this定义的test方法")
    }
}
let stu1 = new Student("tom",23);
console.log(stu1)
console.log( stu1.username )
console.log( stu1.age )
// console.log( Student.username )
// console.log( stu1.test )
stu1.test()

let stu2 = new Student("jack",33);
console.log(stu2)
console.log( stu2.username )
console.log( stu2.age )
stu2.test();

console.log("=======================")
// c. 原型方法(成员方法)的定义
//      + 同过JS语法中为构造方法固定提供prototype属性实现成员方法的定义
//      + 定义语法 ： 构造函数名.prototype.方法名 = 方法取值
//      + 使用语法 ： 实例对象.方法名();
//      + 规则特性 ：
//              => 成员方法不建议使用箭头函数定义，因为会改变方法中this关键字的指向；
//              => 成员方法中的this关键字，指向与当前构造函数构建的实例对象
function Man(username){
    this.username = username;
}
Man.prototype.say = function (){
    console.log("Man.prototype.say",this,this.username)
}
let m1 = new Man("tom");
m1.say();
let m2 = new Man("jack");
m2.say();

console.log("=======================")
console.log( "String-原型方法(成员方法):",String.prototype )
console.log( "Date-原型方法(成员方法):",Date.prototype )
console.log( "Array-原型方法(成员方法):",Array.prototype )

console.log("=======================")
// ES6 引入了 类似与 java 面向对象的语言体系
//    +  class  extends
//    + class 关键字的引入，实际上就是对上述的原始面向对象开发语法的重新定义
class Dog {
//  静态属性的定义和赋值
    static info = "静态属性";
//  成员属性声明
    arg;
//  成员属性声明 + 赋值
    arg1 = "默认值"
//    构造器
    constructor(type,arg) {
        console.log("Dog构造函数")
        //成员属性声明 + 赋值
        this.type = type;
        // 赋值
        this.arg = arg;
    }
//    直接在class中定义的方式为成员方法 -> 直接定义在 prototype 上的方法
    printTestFun(){
        console.log("成员方法")
    }
//    静态方法
    static tipTestFun(){
        console.log("静态方法")
    }
}
let d1 = new Dog("哈士奇","成员参数");
console.log(d1)
d1.printTestFun()
console.log( Dog.prototype )
console.log( Dog.info )
Dog.tipTestFun();


console.log("=======================")
//  方式 2 : 字面量方式创建对象
//          ==> 不能构建 静态属性 静态方法 成员方法
let user1 = {}; // 定义了一个空对象
console.log( user1 )

let user2 = {
//    key:value  => key 成员属性名  ； value 成员属性值
    name:"tom",
    age:23,
    sex:'男',
    test:function (){},
    arr:[1,2,3,4],
    obj:{
        a:1,
        b:2
    }
}
console.log( user2 )









